package mz.co.research.client.view;

import java.util.Collection;
import java.util.List;

import mz.co.research.client.view.component.TabSet;
import mz.co.research.client.view.component.Table;
import mz.co.research.client.view.model.DataView;
import mz.co.research.shared.model.AnswerDomain;
import mz.co.research.shared.model.AnswerDomainItem;
import mz.co.research.shared.model.AnswerType;
import mz.co.research.shared.model.CheckboxType;
import mz.co.research.shared.model.Form;
import mz.co.research.shared.model.MultiSelectType;
import mz.co.research.shared.model.Question;
import mz.co.research.shared.model.RadioType;
import mz.co.research.shared.model.Research;
import mz.co.research.shared.model.SelectType;
import mz.co.research.shared.model.TextType;
import mz.co.research.shared.services.IAnswerService;
import mz.co.research.shared.services.IAnswerServiceAsync;
import mz.co.research.shared.services.IResearchService;
import mz.co.research.shared.services.IResearchServiceAsync;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.RunAsyncCallback;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.Constants;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * @author Tiago da Fonseca Frazao
 */
public class CwCreate extends ContentWidget {

	/**
	 * The UiBinder interface used by it.
	 */
	interface CwCreateBinder extends UiBinder<Widget, CwCreate> {
	}

	// Create the UiBinder.
	private static CwCreateBinder uiBinder = GWT.create(CwCreateBinder.class);

	@UiField(provided = true)
	VerticalPanel vHeaderPanel;

	@UiField(provided = true)
	VerticalPanel vContentPanel;

	/**
	 * Create a remote service proxy to talk to the server-side AnswerService
	 * service.
	 */
	private final IAnswerServiceAsync answerService = GWT
			.create(IAnswerService.class);

	/**
	 * Create a remote service proxy to talk to the server-side researchService
	 * service.
	 */
	private final IResearchServiceAsync researchService = GWT
			.create(IResearchService.class);

	/**
	 * The constants used in this Content Widget.
	 */
	public static interface CwConstants extends Constants {
		String cwCreateName();

		String cwCreateDescription();

		String cwCreateResearchCode();

		String cwCreateResearchDescription();

		String cwCreateForm();

		String cwCreateFormCode();

		String cwCreateFormDescription();

		String cwCreateQuestion();

		String cwCreateQuestionCode();

		String cwCreateQuestionDescription();

		String cwCreateQuestionType();

		String cwCreateAnswerDomain();

		String cwCreateAnswerDomainCode();

		String cwCreateAnswerDomainDescription();

		String cwCreateAdd();

		String cwCreateDel();

		String cwCreateSave();
	}

	/**
	 * An instance of the constants.
	 */
	private final CwConstants constants;

	/**
	 * Constructor.
	 * 
	 * @param constants
	 *            the constants
	 */
	public CwCreate(CwConstants constants) {
		super(constants.cwCreateName(), constants.cwCreateDescription(), true);
		this.constants = constants;
	}

	@Override
	public Widget onInitialize() {

		final TextBox researchCode = new TextBox();
		final TextBox researchDescription = new TextBox();

		this.vHeaderPanel = new VerticalPanel();

		Grid grid = new Grid(2, 2);

		grid.setWidget(0, 0, new Label(constants.cwCreateResearchCode()));
		grid.setWidget(0, 1, researchCode);
		grid.setWidget(1, 0, new Label(constants.cwCreateResearchDescription()));
		grid.setWidget(1, 1, researchDescription);

		vHeaderPanel.add(grid);
		this.vContentPanel = new VerticalPanel();

		final FormTab formTab = new FormTab();

		Button add = new Button(constants.cwCreateAdd(), new ClickHandler() {
			public void onClick(ClickEvent event) {
				formTab.addTab();
			}
		});

		Button del = new Button(constants.cwCreateDel(), new ClickHandler() {
			public void onClick(ClickEvent event) {
				formTab.delTab();
			}
		});

		HorizontalPanel buttons = new HorizontalPanel();
		buttons.add(add);
		buttons.add(del);

		vHeaderPanel.add(buttons);
		vContentPanel.add(formTab);

		Button save = new Button(constants.cwCreateSave(), new ClickHandler() {
			public void onClick(ClickEvent event) {
				Research research = new Research();
				research.setCode(researchCode.getValue());
				research.setDescription(researchDescription.getValue());

				@SuppressWarnings("unchecked")
				List<DataView> dvl0 = (List<DataView>) formTab.getDataView()
						.getList("forms");

				for (DataView dv0 : dvl0) {

					final Form form = new Form();
					research.addForm(form);
					form.setCode(((TextBox) dv0.get("code")).getValue());
					form.setDescription(((TextBox) dv0.get("description"))
							.getValue());

					@SuppressWarnings("unchecked")
					List<DataView> dvl1 = (List<DataView>) ((QuestionTab) dv0
							.get("questionTab")).getDataView().getList(
							"questions");

					for (DataView dv1 : dvl1) {
						final Question question = new Question();
						question.setDescription(((TextBox) dv1
								.get("description")).getValue());

						AnswerType answerType = ((AnswerType) dv1
								.get("questionType"));
						question.setAnswerType(answerType);
						String answerTypeCode = answerType.getType();

						form.addQuestion(question);

						if (CheckboxType.TYPE.equals(answerTypeCode)
								|| SelectType.TYPE.equals(answerTypeCode)
								|| MultiSelectType.TYPE.equals(answerTypeCode)
								|| RadioType.TYPE.equals(answerTypeCode)) {

							AnswerDomain answerDomain = new AnswerDomain();

							answerDomain.setCode(((TextBox) dv1
									.get("domainCode")).getValue());
							answerDomain.setDescription(((TextBox) dv1
									.get("domainDescription")).getValue());

							@SuppressWarnings("unchecked")
							List<DataView> dvl2 = (List<DataView>) ((DomainTable) dv1
									.get("domainTable")).getDataView().getList(
									"domains");

							long o = 1;
							for (DataView dv2 : dvl2) {
								AnswerDomainItem answerDomainItem = new AnswerDomainItem();
								answerDomainItem.setCode(((TextBox) dv2
										.get("code")).getValue());
								answerDomainItem.setDescription(((TextBox) dv2
										.get("description")).getValue());
								answerDomainItem.setOrder(o++);

								answerDomain.addItem(answerDomainItem);
							}

							question.setAnswerDomain(answerDomain);
						}

					}

				}

				researchService.gwtCreateResearch(research,
						new AsyncCallback<Void>() {
							@Override
							public void onSuccess(Void result) {
								Window.alert("Ok!");
							}

							@Override
							public void onFailure(Throwable caught) {
								Window.alert("Error - " + caught.getMessage());
							}
						});
			}
		});

		vContentPanel.add(save);

		return uiBinder.createAndBindUi(this);

	}

	@Override
	protected void asyncOnInitialize(final AsyncCallback<Widget> callback) {
		GWT.runAsync(CwCreate.class, new RunAsyncCallback() {

			public void onFailure(Throwable caught) {
				callback.onFailure(caught);
			}

			public void onSuccess() {
				callback.onSuccess(onInitialize());
			}
		});
	}

	private class FormTab extends TabSet {

		public FormTab() {
			super(new DataView(), constants.cwCreateForm(), 1);
		}

		@Override
		public void delTab() {
			super.delTab();

			getDataView().getList("forms").remove(
					getDataView().getList("forms").size() - 1);
		}

		protected Widget createTab() {

			VerticalPanel vPanel = new VerticalPanel();
			vPanel.setWidth("100%");
			vPanel.setHeight("100%");
			vPanel.setSpacing(10);

			VerticalPanel vLayout = new VerticalPanel();

			Grid grid = new Grid(2, 2);

			TextBox code = new TextBox();
			TextBox description = new TextBox();
			grid.setWidget(0, 0, new Label(constants.cwCreateFormCode()));
			grid.setWidget(0, 1, code);
			grid.setWidget(1, 0, new Label(constants.cwCreateFormDescription()));
			grid.setWidget(1, 1, description);

			final QuestionTab questionTab = new QuestionTab();

			Button add = new Button(constants.cwCreateAdd(),
					new ClickHandler() {
						public void onClick(ClickEvent event) {
							questionTab.addTab();
						}
					});

			Button del = new Button(constants.cwCreateDel(),
					new ClickHandler() {
						public void onClick(ClickEvent event) {
							questionTab.delTab();
						}
					});

			HorizontalPanel buttons = new HorizontalPanel();
			buttons.add(add);
			buttons.add(del);

			VerticalPanel vPanel0 = new VerticalPanel();
			vPanel0.setWidth("100%");
			vPanel0.setHeight("30px");
			vPanel0.setSpacing(5);
			vPanel0.add(grid);

			VerticalPanel vPanel1 = new VerticalPanel();
			vPanel1.setWidth("100%");
			vPanel1.setHeight("30px");
			vPanel1.setSpacing(5);

			vPanel1.add(questionTab);

			vPanel.add(vPanel0);
			vPanel.add(buttons);
			vPanel.add(vPanel1);

			vLayout.add(vPanel);

			DataView dataView = new DataView();

			dataView.set("code", code);
			dataView.set("description", description);
			dataView.set("questionTab", questionTab);

			getDataView().add("forms", dataView);

			return vLayout;
		}

	}

	private class QuestionTab extends TabSet {

		public QuestionTab() {
			super(new DataView(), constants.cwCreateQuestion(), 1);
		}

		@Override
		public void delTab() {
			super.delTab();

			getDataView().getList("questions").remove(
					getDataView().getList("questions").size() - 1);
		}

		protected Widget createTab() {

			VerticalPanel vPanel = new VerticalPanel();
			vPanel.setWidth("100%");

			VerticalPanel vLayout = new VerticalPanel();

			final DomainTable domainTable = new DomainTable();

			TextBox domainDescription = new TextBox();
			domainDescription.setSize("55px", "12px");
			TextBox domainCode = new TextBox();
			domainCode.setSize("50px", "12px");

			final HorizontalPanel hPanel = new HorizontalPanel();
			hPanel.setHeight("30px");
			hPanel.add(new Label(constants.cwCreateAnswerDomainCode()));
			hPanel.add(domainCode);
			hPanel.add(new Label(constants.cwCreateAnswerDomainDescription()));
			hPanel.add(domainDescription);

			final VerticalPanel vPanel2 = new VerticalPanel();
			vPanel2.setWidth("100%");
			vPanel2.setHeight("10px");
			vPanel2.add(new Label(constants.cwCreateAnswerDomain()));
			vPanel2.add(hPanel);
			vPanel2.add(domainTable);
			vPanel2.setVisible(false);

			Grid grid = new Grid(2, 2);

			TextBox description = new TextBox();
			grid.setWidget(0, 0,
					new Label(constants.cwCreateQuestionDescription()));
			grid.setWidget(0, 1, description);

			final ListBox listBox = new ListBox();

			Button add = new Button(constants.cwCreateAdd(),
					new ClickHandler() {
						public void onClick(ClickEvent event) {
							domainTable.addItem();
						}
					});

			Button del = new Button(constants.cwCreateDel(),
					new ClickHandler() {
						public void onClick(ClickEvent event) {
							domainTable.delItem();
						}
					});

			final HorizontalPanel buttons = new HorizontalPanel();
			buttons.add(add);
			buttons.add(del);
			buttons.setVisible(false);

			final DataView dataView = new DataView();

			listBox.addChangeHandler(new ChangeHandler() {

				@Override
				public void onChange(ChangeEvent event) {
					int selectedIndex = listBox.getSelectedIndex();
					if (selectedIndex > -1) {
						String value = listBox.getValue(selectedIndex);
						if (CheckboxType.TYPE.equals(value)
								|| SelectType.TYPE.equals(value)
								|| MultiSelectType.TYPE.equals(value)
								|| RadioType.TYPE.equals(value)) {
							vPanel2.setVisible(true);
							buttons.setVisible(true);

						} else {
							vPanel2.setVisible(false);
							buttons.setVisible(false);
							domainTable.reset();
						}

						dataView.set("questionType", dataView.get(value));
					}
				}
			});

			answerService
					.findAnswerTypes(new AsyncCallback<Collection<AnswerType>>() {
						@Override
						public void onSuccess(Collection<AnswerType> result) {

							int i = 0;
							for (AnswerType answerType : result) {
								listBox.addItem(answerType.getDescription(),
										answerType.getType());
								dataView.set(answerType.getType(), answerType);

								if (TextType.TYPE.equals(answerType.getType())) {
									// Selecionando Text como Default
									dataView.set("questionType",
											dataView.get(TextType.TYPE));
									listBox.setSelectedIndex(i);
								}
								i++;
							}

						}

						@Override
						public void onFailure(Throwable caught) {
							Window.alert("Error - " + caught.getMessage());
						}
					});

			grid.setWidget(1, 0, new Label(constants.cwCreateQuestionType()));
			grid.setWidget(1, 1, listBox);

			vPanel.add(grid);
			vPanel.add(buttons);
			vPanel.add(vPanel2);

			vLayout.add(vPanel);

			dataView.set("domainDescription", domainDescription);
			dataView.set("domainCode", domainCode);

			dataView.set("description", description);
			dataView.set("domainTable", domainTable);

			getDataView().add("questions", dataView);

			return vLayout;

		}

	}

	private class DomainTable extends Table {

		public DomainTable() {
			super(new DataView(), 1);
		}

		@Override
		public void delItem() {
			super.delItem();

			getDataView().getList("domains").remove(
					getDataView().getList("domains").size() - 1);
		}

		protected Widget createContent() {

			HorizontalPanel hPanel0 = new HorizontalPanel();

			TextBox code = new TextBox();
			TextBox description = new TextBox();

			hPanel0.add(code);
			hPanel0.add(description);

			DataView dataView = new DataView();

			dataView.set("code", code);
			dataView.set("description", description);

			getDataView().add("domains", dataView);

			return hPanel0;

		}

	}
}
